package cn.com.cennavi.highTraffic;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;

import org.jboss.netty.handler.queue.BufferedWriteHandler;

import scala.Tuple2;

import com.cennavi.mm.astar.Projection;
import com.cennavi.mm.service.RouteEstLocal;
import com.cennavi.mm.thrift.GPS;
import com.cennavi.mm.thrift.RouteEstimationLink;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;

import cn.com.cennavi.bean.DiDiNewData1;
import cn.com.cennavi.bean.DiDiTrajectory;
import cn.com.cennavi.bean.DidiQueue2;
import cn.com.cennavi.bean.DidiQueueStatus2;
import cn.com.cennavi.bean.DifPointTotalMapInfo;
import cn.com.cennavi.util.MapUtil;

/**
 * 测试地面道路用的 批处理程序
 * 
 * @ClassName: HighTrafficComputer
 * @Description: TODO（这里用一句话描述这个类的作用）
 * @author bull
 * @date 2016年11月12日 上午10:09:33
 *
 */
public class HighTrafficComputer_didiStandard_groundRoad_local {
//	static String didifilePath = "D:\\data\\北京地面道路分车道\\北京didi数据\\830-835\\";
	static String didifilePath = "D:\\data\\北京地面道路分车道\\北京didi数据\\515-519\\";
	static String mapFilePath = "D:\\data\\DifPointTotalMapInfo_groundRoad_beijing_20mibuf_北京抽样数据_20mi_西长安街与 府右街交汇处东往西直行.csv";
//	static String mapFilePath = "D:\\data\\DifPointTotalMapInfo_groundRoad_beijing_20mibuf_北京抽样数据_20mi_学院路南向西转入北四环中路.csv";
//	static String mapFilePath = "D:\\data\\DifPointTotalMapInfo_groundRoad_beijing_20mibuf_北京抽样数据_20mi_北花市大街左转崇文门东大街.csv";
//	static String mapFilePath = "D:\\data\\DifPointTotalMapInfo_groundRoad_beijing_30mibuf_北京抽样数据_30mi.csv";
//	static String logFile = "D:\\data\\lane_连续跳出点2，半径10米.log";
//	static String logFile = "D:\\data\\lane_连续跳出点2，半径20米_学院路南向西转入北四环中路.log";
	static String logFile = "D:\\data\\lane_连续跳出点2，半径20米_西长安街与 府右街交汇处东往西直行.log";
//	static String logFile = "D:\\data\\lane_连续跳出点2，半径20米_北花市大街左转崇文门东大街.log";
//	static String logFile = "D:\\data\\lane_连续跳出点2，半径30米.log";
	// static String logFile = "D:\\data\\lane_连续跳出点10，半径5米.log";
	// static int car_keepErrorPoint=10;
	static int car_keepErrorPoint = 2;
	static HashSet<Integer> meshSet = new HashSet<Integer>();
	static BufferedWriter o = null;

	static void init() throws IOException {
		//西长安街与 府右街交汇处东往西直行
		meshSet.add(595662);
		meshSet.add(595663);
//		//学院路南向西转入北四环中路
//		meshSet.add(595672);
		o = new BufferedWriter(new FileWriter(new File(logFile), false));
	}

	// -------------------------------------------------------------------------------------------------------------
	public static void main(String[] args) throws IOException, ParseException {
		init();
		// 1.数据过滤
		// 2.数据按照时间排序
		// 3.缓冲区匹配
		// 4.计算单车具体位置的平均速度值,返回：每一分钟每辆车的每一个位置的速度平均值
		// -----------------------------------
		// // 得到缓冲区数据
		ArrayList<DifPointTotalMapInfo> difPointTotalMapInfo = readMapDataFile(mapFilePath);
		// 得到每辆车，按照时间排序后的数据，目前读取的是连续的5分钟数据
		HashMap<String, TreeMap<Long, DiDiNewData1>> didiCarMap = readDiDiDataFile(didifilePath, meshSet);
		// 得到每辆车的能够进行匹配的缓冲区点序列
		HashMap<String, ArrayList<DidiQueue2>> didiTrajectory = getMatchPointsData(didiCarMap, difPointTotalMapInfo);
		// 对得到的缓冲区点序列进行匹配
		HashMap<String, ArrayList<DiDiTrajectory>> matchMap = matchData(didiTrajectory);

		// 对匹配出来的数据，求平均速度
		HashMap<String, ArrayList<String>> carSpeed = getGPSAverageSpeedInfo(matchMap);

		// 相同位置速度聚类
		String filePath = "D:\\data\\分车道校验\\地面道路\\地面道路分歧点3054628东向西直行_20mibuffer西长安街与 府右街交汇处东往西直行515-519.csv";
////		String filePath = "D:\\data\\分车道校验\\地面道路\\Untitled1.csv";
//		String filePath = "D:\\data\\分车道校验\\地面道路\\地面道路分歧点3054628东向西直行_20mibuffer.csv";
//		String filePath = "D:\\data\\分车道校验\\地面道路\\地面道路分歧点3054628东向西直行_20mibuffer_北花市大街左转崇文门东大街515-519.csv";
//		getMixSpeed(filePath);

	}

	private static class _LaneSpeedClass {
		public double speed;
		public String carId;
		public int min;
		public long timestamp;
		public int dis;

		public _LaneSpeedClass(double speed, String carId, int min, long timestamp, int dis) {
			this.speed = speed;
			this.carId = carId;
			this.min = min;
			this.timestamp = timestamp;
			this.dis = dis;
		}
	}

	private static void getMixSpeed(String filePath) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new FileReader(new File(filePath)));

		//
		TreeMap<Integer, ArrayList<_LaneSpeedClass>> dataMap = new TreeMap<Integer, ArrayList<_LaneSpeedClass>>();
		HashMap<String, TreeMap<Integer, _LaneSpeedClass>> carDisSpeedMap = new HashMap<String, TreeMap<Integer, _LaneSpeedClass>>();

		// 获取数据
		getData(dataMap, carDisSpeedMap, br);
		br.close();

//		// 得到每辆车红绿灯影响范围
//		HashMap<String, String> carDisArea = getEveryCarLightInfluenceArea(carDisSpeedMap);

		// 将匹配出来的速度值中包含（红绿灯影响范围的速度点）去掉，和没去掉比较
		// getMixSpeedAverageWithoutTrafficLight(dataMap, speedDiff,
		// speedLight,carDisArea);
		//
		// // 速度聚类求平均，加验证
		getMixSpeedAverage(dataMap);

		//
	}

	private static void getMixSpeedAverageWithoutTrafficLight(TreeMap<Integer, ArrayList<_LaneSpeedClass>> dataMap, int speedDiff, int speedLight, HashMap<String, String> carDisArea) {
		// TODO Auto-generated method stub
		for (Map.Entry<Integer, ArrayList<_LaneSpeedClass>> entry : dataMap.entrySet()) {
			int distance = entry.getKey();
			// System.out.println(distance);
			// System.out.println("-----");
			ArrayList<_LaneSpeedClass> dataList = entry.getValue();
			TreeMap<Double, Double> treeMap = new TreeMap<Double, Double>();
			TreeMap<Double, Double> treeMapWithOutLight = new TreeMap<Double, Double>();
			for (_LaneSpeedClass ld : dataList) {
				// System.out.println(ld.speed + "," + ld.min + "," + ld.carId);
				treeMap.put(ld.speed, ld.speed);
				if (!judgeIsInTrafficLightArea(ld.carId, distance, carDisArea)) {
					treeMapWithOutLight.put(ld.speed, ld.speed);
				} else {
					// System.out.println("上面点去掉");
				}
			}
			// System.out.println("-----");
			System.out.println(distance + treeMap.firstKey() + "," + treeMap.lastKey() + "," + (treeMap.lastKey() - treeMap.firstKey()));
			// System.out.println("-----");
			// System.out.println("跑出红绿灯影响范围:"+treeMapWithOutLight.firstKey() +
			// "," + treeMapWithOutLight.lastKey() + "," +
			// (treeMapWithOutLight.lastKey() -
			// treeMapWithOutLight.firstKey()));
			// System.out.println("-------------------");
		}
	}

	private static boolean judgeIsInTrafficLightArea(String carId, int distance, HashMap<String, String> carDisArea) {
		// TODO Auto-generated method stub
		String[] ss = carDisArea.get(carId).split("\\_");
		int minDis = Integer.parseInt(ss[0]);
		int maxDis = Integer.parseInt(ss[1]);
		if (distance >= minDis && distance <= maxDis) {
			return true;
		}
		return false;
	}

	/**
	 * 找出每辆车的速度最小值（等待红绿灯） 和 速度最小值附近的影响区域
	 * 
	 * @param carDisSpeedMap
	 */
	private static HashMap<String, String> getEveryCarLightInfluenceArea(HashMap<String, TreeMap<Integer, _LaneSpeedClass>> carDisSpeedMap) {
		// TODO Auto-generated method stub
		HashMap<String, String> carDisArea = new HashMap<String, String>();
		for (Map.Entry<String, TreeMap<Integer, _LaneSpeedClass>> entry : carDisSpeedMap.entrySet()) {
			String carId = entry.getKey();
			TreeMap<Integer, _LaneSpeedClass> carInfo = entry.getValue();
			// 获取一辆车速度最小点位置
			String dis = getMinSpeedPos(carInfo);
			// 获取最小点速度的影响范围
			String minArea = getMinArea(carInfo, dis);
			carDisArea.put(carId, minArea);

		}
		for (Map.Entry<String, String> e1 : carDisArea.entrySet()) {
			// System.out.println(e1.getKey() + "," + e1.getValue());
		}
		return carDisArea;
	}

	private static String getMinArea(TreeMap<Integer, _LaneSpeedClass> carInfo, String dis_speed) {
		// TODO Auto-generated method stub
		int minDis = carInfo.firstKey();
		int maxDis = carInfo.lastKey();
		String[] dis_speedArr = dis_speed.split("\\_");
		int dis = Integer.parseInt(dis_speedArr[0]);
		double speed = Double.parseDouble(dis_speedArr[1]);
		for (int i = dis; i >= carInfo.firstKey() + 1; i--) {
			double nowSpeed = carInfo.get(i).speed;
			double befSpeed = carInfo.get(i - 1).speed;
			if (befSpeed - nowSpeed < 0) {
				minDis = i;
				break;
			}
		}
		double statardspeed = carInfo.get(minDis).speed;
		for (int i = minDis; i <= carInfo.lastKey() + 1; i++) {
			if(carInfo.get(i)==null){
				continue;
			}
			double nowSpeed = carInfo.get(i).speed;

			if (nowSpeed != statardspeed) {
				minDis = i;
				break;
			}
		}
//		for(Map.Entry<Integer, _LaneSpeedClass>eee:carInfo.entrySet()){
//			System.out.println(+eee.getKey()+"."+eee.getValue().speed);
//		}
		for (int i = dis; i <= carInfo.lastKey() - 1; i++) {
			if(carInfo.get(i)==null||carInfo.get(i+1)==null){
				continue;
			}
			double nowSpeed = carInfo.get(i).speed;
			double aftSpeed = carInfo.get(i + 1).speed;
			if (aftSpeed - nowSpeed < 0) {
				maxDis = i;
				break;
			}
		}
		return minDis + "_" + maxDis;
	}

	private static String getMinSpeedPos(TreeMap<Integer, _LaneSpeedClass> carInfo) {
		// TODO Auto-generated method stub
		double minspeed = 500;
		int mindis = 0;
		double minSpeed = 0;
		for (Map.Entry<Integer, _LaneSpeedClass> e1 : carInfo.entrySet()) {
			int dis = e1.getKey();
			double nowSpeed = e1.getValue().speed;
			minspeed = (nowSpeed - minspeed > 0 ? minspeed : nowSpeed);
			if (nowSpeed - minspeed <= 0) {
				mindis = dis;
				minSpeed = minspeed;
			}
		}
		return mindis + "_" + minspeed;
	}

	private static void getData(TreeMap<Integer, ArrayList<_LaneSpeedClass>> dataMap, HashMap<String, TreeMap<Integer, _LaneSpeedClass>> carDisSpeedMap, BufferedReader br) throws NumberFormatException, IOException {
		// TODO Auto-generated method stub
		String line = "";
		while ((line = br.readLine()) != null) {
			String[] lineArr = line.split(",");
			int min = Integer.parseInt(lineArr[0]);
//			if(!(min>=519&&min<=519)){
//				continue;
//			}
			int dis = Integer.parseInt(lineArr[1]);
			double speed = Double.parseDouble(lineArr[2]);

			String carID = lineArr[3];
			long timestamp = Long.parseLong(lineArr[4]);
			_LaneSpeedClass lsc = new _LaneSpeedClass(speed, carID, min, timestamp, dis);
			if (dataMap.containsKey(dis)) {
				ArrayList<_LaneSpeedClass> data = dataMap.get(dis);
				data.add(lsc);
			} else {
				ArrayList<_LaneSpeedClass> data = new ArrayList<HighTrafficComputer_didiStandard_groundRoad_local._LaneSpeedClass>();
				data.add(lsc);
				dataMap.put(dis, data);
			}
			if (carDisSpeedMap.containsKey(carID)) {
				TreeMap<Integer, _LaneSpeedClass> carMap = carDisSpeedMap.get(carID);
				carMap.put(lsc.dis, lsc);
			} else {
				TreeMap<Integer, _LaneSpeedClass> carMap = new TreeMap<Integer, _LaneSpeedClass>();
				carMap.put(lsc.dis, lsc);
				carDisSpeedMap.put(carID, carMap);
			}
		}
	}

	private static void getMixSpeedAverage(TreeMap<Integer, ArrayList<_LaneSpeedClass>> dataMap) {
		// TODO Auto-generated method stub
		for (Map.Entry<Integer, ArrayList<_LaneSpeedClass>> entry : dataMap.entrySet()) {
			int distance = entry.getKey();
//			if (distance == 155) {
//				System.out.println("");
//			}
			ArrayList<_LaneSpeedClass> dataList = entry.getValue();
			TreeMap<Double, ArrayList<Long>> treeMap = new TreeMap<Double, ArrayList<Long>>();
			TreeMap<Long, ArrayList<Double>> timetreeMap = new TreeMap<Long, ArrayList<Double>>();
			for (_LaneSpeedClass ld : dataList) {
				if (treeMap.containsKey(ld.speed)) {
					treeMap.get(ld.speed).add(ld.timestamp);
				} else {
					ArrayList<Long> dd = new ArrayList<Long>();
					dd.add(ld.timestamp);
					treeMap.put(ld.speed, dd);
				}
				if (timetreeMap.containsKey(ld.timestamp)) {
					timetreeMap.get(ld.timestamp).add(ld.speed);
				} else {
					ArrayList<Double> dd = new ArrayList<Double>();
					dd.add(ld.speed);
					timetreeMap.put(ld.timestamp, dd);
				}
			}
			// System.out.println(distance+","+treeMap.firstKey() + "," +
			// treeMap.lastKey() + "," + (treeMap.lastKey() -
			// treeMap.firstKey()));

			double minspeed = treeMap.firstKey();
			// 求最高速度值第一版，直接取速度最大值。
			// double maxspeed = treeMap.lastKey();
			// 改进一：只有当前值不超过前后30秒内错有速度均值2倍的时候才算，主要是为了排除加塞的情况
			double maxspeed = getMaxSpeed(timetreeMap, treeMap);
			double speedDiff = maxspeed / 2;
			double sumSpeeds = 0;
			int num = 0;
			for (_LaneSpeedClass ld : dataList) {
				if (ld.speed >= speedDiff) {
					sumSpeeds += ld.speed;
					num++;
				}
			}
			double averageSpeed = sumSpeeds / num;
			System.out.println(distance + "," + averageSpeed + "," + speedDiff + "," + treeMap.firstKey() + "," + treeMap.lastKey() + "," + (treeMap.lastKey() - treeMap.firstKey()));

		}
	}

	/**
	 * 从相同位置，按照时间排好序的速度值中找到最大的最合适的速度值
	 * 
	 * @param timetreeMap
	 * @param treeMap
	 * @return
	 */
	private static double getMaxSpeed(TreeMap<Long, ArrayList<Double>> timetreeMap, TreeMap<Double, ArrayList<Long>> treeMap) {
		// TODO Auto-generated method stub
		NavigableMap<Double, ArrayList<Long>> speed_time_map = treeMap.descendingMap();
		for (Entry<Double, ArrayList<Long>> e : speed_time_map.entrySet()) {
			double speed = e.getKey();
			ArrayList<Long> nowtimes = e.getValue();
			for (long nowtime : nowtimes) {
				long minTime = nowtime - 29;
				long maxTime = nowtime + 29;
				int sumSpeed = 0;
				int pointNum = 0;
				for (long time = minTime; time <= maxTime; time++) {
					if (timetreeMap.containsKey(time)) {
						ArrayList<Double> speeds = timetreeMap.get(time);

						for (double speed1 : speeds) {
							if (time == nowtime && speed1 != speed) {
								sumSpeed += speed1;
								pointNum++;
							}
							if (time != nowtime) {
								sumSpeed += speed1;
								pointNum++;
							}
						}
					}
				}
				double averageSpeed;
				if (pointNum != 0) {
					averageSpeed = sumSpeed / pointNum;
					if (speed < (averageSpeed * 2)) {
						return speed;
					}
				} else {
					return speed;
				}
			}

		}
		return 0;
	}

	/**
	 * 计算每辆车的某一位置上的速度
	 * 
	 * @param matchMap
	 * @return
	 */
	private static HashMap<String, ArrayList<String>> getGPSAverageSpeedInfo(HashMap<String, ArrayList<DiDiTrajectory>> matchMap) {
		// TODO Auto-generated method stub
		for (Map.Entry<String, ArrayList<DiDiTrajectory>> entry : matchMap.entrySet()) {
			String carId = entry.getKey();
			ArrayList<DiDiTrajectory> arrayList = entry.getValue();
			for (DiDiTrajectory diDiTrajectory : arrayList) {
				String key1 = diDiTrajectory.toShowString();
				String[] gpsDisArr = diDiTrajectory.gpsDisSeq.split("\\|");
				String[] gpsTimeArr = diDiTrajectory.gpsTimeSeq.split("\\|");
				// 用于保存标准gps点的瞬时速度
				String[] speedArr = diDiTrajectory.speedSeq.split("\\|");
				if (gpsTimeArr.length <= 1 || gpsDisArr.length <= 1 || (gpsDisArr.length != gpsTimeArr.length))
					continue;
				for (int i = 0; i < gpsTimeArr.length - 1; i++) {
					long timeStamp = Long.parseLong(gpsTimeArr[i]);
					int length = (int) Double.parseDouble(gpsDisArr[i]);
					long afterTimeStamp = Long.parseLong(gpsTimeArr[i + 1]);
					int afterLength = (int) Double.parseDouble(gpsDisArr[i + 1]);
					String speed = speedArr[i];
					double aveSpeed = (double) (Math.abs((afterLength - length) / (double) (afterTimeStamp - timeStamp)) * 3.6);
					if (aveSpeed > 150) {
						continue;
					}
					if (timeStamp - afterTimeStamp >= 0) {
						continue;
					}
					if (afterLength - length >= 0) {
						continue;
					}

					for (int j = afterLength; j < length; j++) {
						String key = key1 + "_" + j;
						String value = getMin(diDiTrajectory.timeStamp) + "_" + key + "_" + aveSpeed + "_" + carId + ":" + timeStamp;
						 System.out.println(value);
					}
				}
			}
		}
		return null;
	}

	public static int getMin(long time) {
		Date date = new Date(time * 1000);
		SimpleDateFormat sf = new SimpleDateFormat("HH");
		SimpleDateFormat mf = new SimpleDateFormat("mm");
		int min = Integer.parseInt(sf.format(date)) * 60 + Integer.parseInt(mf.format(date));
		return min;
	}

	private static HashMap<String, ArrayList<DiDiTrajectory>> matchData(HashMap<String, ArrayList<DidiQueue2>> didiTrajectory) throws IOException {
		// TODO Auto-generated method stub
		HashMap<String, ArrayList<DiDiTrajectory>> returnMap = new HashMap<String, ArrayList<DiDiTrajectory>>();
		for (Map.Entry<String, ArrayList<DidiQueue2>> entry : didiTrajectory.entrySet()) {
			String carId = entry.getKey();
			ArrayList<DidiQueue2> queueList = entry.getValue();
			for (DidiQueue2 didiQueuq : queueList) {
				LinkedList<DiDiNewData1> enterBufQueue = didiQueuq.enterBufQueue;
				// LinkedList<DiDiNewData1> cacheQueue = arg0._2.cacheQueue;
				HashMap<String, DifPointTotalMapInfo> difPoint_dir_bufferMap = didiQueuq.difPoint_dir_bufferMap;
				String key = carId;
				if (key.equals("564132154052609")) {
					// System.out.println("564132154052609");
				}
				RouteEstLocal re = null;
				DiDiTrajectory didi = null;
				try {
					re = new RouteEstLocal("172.20.10.141:9001", new HashMap<String, String>(), "1");
					TreeMap<Long, GPS> gpsMap = new TreeMap<>();
					// o.write(carId);
					for (DiDiNewData1 odb : enterBufQueue) {
						GPS gps = new GPS(odb.lon, odb.lat, odb.direction, odb.timeStamp, (int) (odb.speed));
						o.write(odb.lon + "," + odb.lat + "," + odb.timeStamp + "," + carId + "," + "222");
						o.newLine();
						o.flush();
						gpsMap.put(gps.time, gps);
					}
					// o.write("----------------------------");
					// o.write("niuxinzan:现在缓冲区点id：" +
					// difPoint_dir_bufferMap.keySet().toString());
					// 如果候选buffer不是唯一的，则不进行匹配了
					if (difPoint_dir_bufferMap.size() != 1) {
						o.write("error");
					}
					if (gpsMap.size() < 2) {
						o.write("error");
					}
					List<RouteEstimationLink> trace = re.getRoute(gpsMap, true);

					String linkseq;
					if (trace != null) {
						linkseq = judgeRoadIsDifPointRoad(trace, difPoint_dir_bufferMap);
						if (linkseq != null) {
							didi = DiDiTrajectory.getDiDiTrajectory(key, linkseq);
						}
					}
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				} finally {
					re.close();
				}
				if (didi != null) {
					//有匹配成功的数据
					System.out.println("有匹配成功的数据:"+didi.toString1());
					if (returnMap.containsKey(key)) {
						ArrayList<DiDiTrajectory> value = returnMap.get(key);
						value.add(didi);
					} else {
						ArrayList<DiDiTrajectory> value = new ArrayList<DiDiTrajectory>();
						value.add(didi);
						returnMap.put(key, value);
					}
				} else {
				}
			}
		}
		for (Map.Entry<String, ArrayList<DiDiTrajectory>> entry1 : returnMap.entrySet()) {
			o.write(entry1.getKey());
			o.newLine();
			o.flush();
			ArrayList<DiDiTrajectory> ddlist = entry1.getValue();
			for (DiDiTrajectory dd : ddlist) {
				o.write(dd.toString1());
				o.newLine();
				o.flush();
			}
			o.write("---------------------------");
			o.newLine();
			o.flush();
		}
		return returnMap;
	}

	private static String judgeRoadIsDifPointRoad(List<RouteEstimationLink> trace, HashMap<String, DifPointTotalMapInfo> difPoint_dir_bufferMap) {
		// TODO Auto-generated method stub

		// 判断是不是有交集，如果有把相交的部分提取出来

		String links = "";

		// linkid按照时间排序，保存排好序的位置和速度

		HashMap<String, TreeMap<Long, String>> link_dis_speed_list = new HashMap<>();

		// 1得到每条link的上gps点投影位置和速度值，2得到匹配出来的link序列

		try {

			// 循环便利，得到每条link包含的投影点信息，和link序列

			for (int i = 0; i < trace.size(); i++) {

				ArrayList<Projection> proj = trace.get(i).projList;
				if (proj == null)
					continue;
				for (Projection projection : proj) {
					String linkId = projection.linkID;
					double dis = projection.prjDistanceFormSNode;
					long timeStamp = projection.gps.time;
					// System.out.println(timeStamp);
					int Speed = projection.gps.speed;
					double len = projection.linkLenth;
					TreeMap<Long, String> linkTreeMap = link_dis_speed_list.get(linkId);
					if (linkTreeMap == null) {
						TreeMap<Long, String> linkTreeMap1 = new TreeMap<>();
						linkTreeMap1.put(timeStamp, dis + "_" + Speed + "_" + len);
						link_dis_speed_list.put(linkId, linkTreeMap1);
					} else {
						linkTreeMap.put(timeStamp, dis + "_" + Speed + "_" + len);
					}
				}
				links += trace.get(i).linkID;
				if (i != trace.size() - 1) {
					links += "|";
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		// 判断links序列是否包含备选缓冲区的进出口link
		// 20161116
		// 因为前面封闭道路的时候做过判断，如果一条道路匹配出两个或两个以上缓冲区，则舍弃；这里地面道路因为只输入一个方向道路的数据，所以备选缓冲区只有一个
		// 新加，匹配出来的link至少包含分歧点前后两条link
		String[] inoutlink = difPoint_dir_bufferMap.entrySet().iterator().next().getValue().enter_out_DifPoint_Link.split("\\|");
		boolean hasInOutLink = judgeHasInOutLink(links, inoutlink);
		if (!hasInOutLink)
			return null;
		// 判断link序列与候选缓冲区link的交集
		for (Map.Entry<String, DifPointTotalMapInfo> entry1 : difPoint_dir_bufferMap.entrySet()) {
			String difPointId_dir = entry1.getKey();
			DifPointTotalMapInfo totalMapInfo = entry1.getValue();
			String linkSeq1 = totalMapInfo.linkArr;
			String[] geoLinks = linkSeq1.split("\\|");
			String linkeq = "", StartLink = "";
			int num = -1;
			for (int i = 0; i < geoLinks.length; i++) {
				if (links.contains(geoLinks[i])) {
					StartLink = geoLinks[i];
					linkeq = StartLink;
					num = i;
					break;
				}
			}
			if (num == -1) {
				continue;
			}
			// 判断分歧点后是否有数据
			// 说明只匹配出来一条link，而且还是最后一条link，这种情况我们应该在前面（匹配出来的link至少包含分歧点前后两条link）就排除掉了
			if (num == geoLinks.length - 1) {

				// 这个地方不会走
				System.out.println("这个地方不会走,正式版需要注释掉");
				continue;
				// // 分歧点id和方向、分歧点道路的所有link、匹配出来的分歧点道路的link
				// // 得到匹配出来的link序列，linkeq,根据linkeq顺序获取link的投影信息
				// String[] linksArr = linkeq.split("\\|");
				// StringBuffer timeSb = new StringBuffer();
				// // gps点序列 距离最末尾link的距离
				// StringBuffer disSb = new StringBuffer();
				// StringBuffer speedSb = new StringBuffer();
				// // 计算每条link距离最末尾link的距离
				// HashMap<String, Integer> linkToStartLenMap =
				// getLinkToStartLenMap(totalMapInfo, linksArr);
				//
				// for (String link : linksArr) {
				// TreeMap<Long, String> map = link_dis_speed_list.get(link);
				// for (Map.Entry<Long, String> entry : map.entrySet()) {
				// long time = entry.getKey();
				// // 相同时间戳只保存一次
				// if (timeSb.toString().contains(time + "")) {
				// continue;
				// }
				// String[] dis_speed = entry.getValue().split("\\_");
				// // 匹配投影点在link两端的舍弃
				// if (Double.parseDouble(dis_speed[0]) == 0 ||
				// (linkToStartLenMap.get(link) -
				// Double.parseDouble(dis_speed[0])) == 0) {
				// continue;
				// }
				// // timeSb.append(entry.getKey());
				// // timeSb.append("|");
				// // 计算gps点距离最末尾link的距离
				// int disFromEnd = (int) (linkToStartLenMap.get(link) -
				// Double.parseDouble(dis_speed[0]));
				// // 计算gps点距离同一方向分叉了的公共部分的最后一条link的距离
				// int disFromMinSameLinkDis = disFromEnd -
				// totalMapInfo.minSuitableDisFromLastLink;
				// int difPointDisFromMinSameLinkDis =
				// totalMapInfo.difPoint_startDis -
				// totalMapInfo.minSuitableDisFromLastLink;
				// //
				// if(disFromMinSameLinkDis<difPointDisFromMinSameLinkDis)hasDataAfterDifPoint=true;
				// // 如果gps点落在同一方向（比方左转）但是有分叉的道路的公共部分，则保存，否则为无效数据
				// if (disFromMinSameLinkDis >= 0 && disFromMinSameLinkDis <=
				// totalMapInfo.samelinkLen) {
				// timeSb.append(entry.getKey());
				// timeSb.append("|");
				// disSb.append(disFromMinSameLinkDis);
				// disSb.append("|");
				// speedSb.append(dis_speed[1]);
				// speedSb.append("|");
				// }
				//
				// }
				// }
				//
				// // 分歧点id和方向、分歧点道路的所有link、匹配出来的分歧点道路的link
				// return difPointId_dir + ":" + linkSeq1 + ":" + linkeq + ":" +
				// totalMapInfo.toString() + ":" + timeSb.toString() + ":" +
				// disSb.toString() + ":" + speedSb.toString();
			}

			for (int j = num + 1; j < geoLinks.length; j++) {
				linkeq += "|";
				linkeq += geoLinks[j];
				if (links.contains(linkeq)) {
					StartLink = linkeq;
				} else {
					break;
				}
			}
			// 得到匹配出来的link序列，StartLink,根据StartLink顺序获取link的投影信息
			String[] linksArr = StartLink.split("\\|");
			StringBuffer timeSb = new StringBuffer();
			StringBuffer disSb = new StringBuffer();
			StringBuffer speedSb = new StringBuffer();
			HashMap<String, Integer> linkToStartLenMap = getLinkToStartLenMap(totalMapInfo, linksArr);
			for (String link : linksArr) {
				TreeMap<Long, String> map = link_dis_speed_list.get(link);
				if (map != null)
					for (Map.Entry<Long, String> entry : map.entrySet()) {
						long time = entry.getKey();
						// 保证匹配点的顺序性
						if (timeSb.toString().contains(time + "")) {
							continue;
						}
						String[] dis_speed = entry.getValue().split("\\_");
						// 匹配到link端点出舍弃
						double diss = Double.parseDouble(dis_speed[0]);
						double lenLink = Double.parseDouble(dis_speed[2]);
						if (diss == 0 || diss == lenLink) {
							continue;
						}
						// 计算gps点距离最末尾link的距离
						int disFromEnd = (int) (linkToStartLenMap.get(link) - Double.parseDouble(dis_speed[0]));
						// 计算gps点距离同一方向分叉了的公共部分的最后一条link的距离
						int disFromMinSameLinkDis = disFromEnd - totalMapInfo.minSuitableDisFromLastLink;
						int difPointDisFromMinSameLinkDis = totalMapInfo.difPoint_startDis - totalMapInfo.minSuitableDisFromLastLink;
						// if(disFromMinSameLinkDis<difPointDisFromMinSameLinkDis)hasDataAfterDifPoint=true;
						// 如果gps点落在同一方向（比方左转）但是有分叉的道路的公共部分，则保存，否则为无效数据
						if (disFromMinSameLinkDis >= 0 && disFromMinSameLinkDis <= totalMapInfo.samelinkLen) {
							timeSb.append(entry.getKey());
							timeSb.append("|");
							disSb.append(disFromMinSameLinkDis);
							disSb.append("|");
							speedSb.append(dis_speed[1]);
							speedSb.append("|");
						}
					}
			}
			// if (timeSb != null&&hasDataAfterDifPoint)
			return difPointId_dir + ":" + linkSeq1 + ":" + StartLink + ":" + totalMapInfo.toString() + ":" + timeSb.toString() + ":" + disSb.toString() + ":" + speedSb.toString();
		}
		return null;
	}

	private static boolean judgeHasInOutLink(String links, String[] inoutlink) {
		// TODO Auto-generated method stub
		if (links.contains(inoutlink[0]) && links.contains(inoutlink[1])) {
			return true;
		} else {
			return false;
		}
	}

	private static HashMap<String, Integer> getLinkToStartLenMap(DifPointTotalMapInfo totalMapInfo, String[] linksArr) {
		// TODO Auto-generated method stub
		// TODO Auto-generated method stub
		HashMap<String, Integer> dataMap = new HashMap<>();
		String[] linksLen = totalMapInfo.linksLen.split("\\|");
		int len = linksLen.length;
		int length = 0;
		for (int i = len - 1; i >= 0; i--) {
			String[] linkId_len = linksLen[i].split("\\:");
			String linkId = linkId_len[0];
			length += Integer.parseInt(linkId_len[1]);
			dataMap.put(linkId, length);
		}
		return dataMap;
	}

	/**
	 * 匹配推测
	 * 
	 * @param didiCarMap
	 * @param difPointTotalMapInfo
	 * @return
	 * @throws IOException
	 */
	private static HashMap<String, ArrayList<DidiQueue2>> getMatchPointsData(HashMap<String, TreeMap<Long, DiDiNewData1>> didiCarMap, ArrayList<DifPointTotalMapInfo> difPointTotalMapInfo) throws IOException {
		// TODO Auto-generated method stub
		// DidiQueueStatus2 returnStatus = new DidiQueueStatus2();
		HashMap<String, DidiQueueStatus2> returnStatuses = new HashMap<String, DidiQueueStatus2>();
		HashMap<String, ArrayList<DidiQueue2>> returnList = new HashMap();
		for (Map.Entry<String, TreeMap<Long, DiDiNewData1>> entry : didiCarMap.entrySet()) {
			String carId = entry.getKey();
			DidiQueueStatus2 returnStatus = returnStatuses.get(carId);
			if (returnStatus == null) {
				returnStatus = new DidiQueueStatus2();
			}
			TreeMap<Long, DiDiNewData1> timeLine = entry.getValue();
			// if (carId.equals("564132154052609")) {
			// System.out.println("564132154052609");
			// }
			DiDiNewData1 beforeData = timeLine.firstEntry().getValue();
			int i = 0;

			for (Map.Entry<Long, DiDiNewData1> entry1 : timeLine.entrySet()) {
				DidiQueue2 returnQueue = null;
				long nowTime = entry1.getKey();
				// System.out.println(nowTime);
				DiDiNewData1 didi = entry1.getValue();
				// 对于重叠gps点，过滤掉
				if ((beforeData.lon == didi.lon) && (beforeData.lat == didi.lat)&&i!=0) {
					beforeData = didi;
					continue;
				}
				HashMap<String, DifPointTotalMapInfo> linkGeoList ;
				/** 如果gps点落在某一条或多条道路的缓冲区域内，写入缓存序列 **/
				/** 判断是不是在该网格中分歧点道路缓冲区内，key：pointId+dir **/
				if(didi.carID.equals("565149518997791")){
					linkGeoList = judgeIsInBufferArea(didi, difPointTotalMapInfo, beforeData, i);
					if (i == 0) {
						i++;
//						linkGeoList.clear();
					}
				}else{
					linkGeoList = judgeIsInBufferArea(didi, difPointTotalMapInfo, beforeData, i);
					if (i == 0) {
						i++;
//						linkGeoList.clear();
					}
				}
			
				// 赋值
				beforeData = didi;

				didi.difPointId = getDifPointId(linkGeoList);
				/**
				 * 只有匹配完后才会有cachegps点
				 * 如果cache缓冲区有缓存的gps点，考虑是不是应该加入到enterBufQueue中
				 * 1：第一次进来后，如果gps点有缓冲区，则判断是不是需要添加cache。如果没有缓冲区则直接pass。
				 **/
				if (returnStatus.cacheQueue.size() != 0) {
					if (!didi.difPointId.equals("")) {
						judgeIsInCacheBufferArea(didi, returnStatus);
						returnStatus.enterBufQueue.add(didi);
						/** 讲该辆车的所属缓冲区保存 **/
						returnStatus.difPoint_dir_bufferMap = linkGeoList;
					}
					returnStatus.cacheQueue.clear();
				} else {
					// 之前没有缓存点了，第二个点进来
					HashMap<String, DifPointTotalMapInfo> linkGeoList_bef = returnStatus.difPoint_dir_bufferMap;
					if (returnStatus.enterBufQueue.size() == 0 && didi.difPointId.equals("")) {
						continue;
					}
					if (returnStatus.enterBufQueue.size() == 0 && !didi.difPointId.equals("")) {
						returnStatus.enterBufQueue.add(didi);
						/** 讲该辆车的所属缓冲区保存 **/
						returnStatus.difPoint_dir_bufferMap = linkGeoList;
						continue;
					}
					if (returnStatus.enterBufQueue.size() != 0 && didi.difPointId.equals("")) {
						if (returnStatus.car_keepErrorPoint >= car_keepErrorPoint) {
							// 生成输出点序对象
							returnQueue = new DidiQueue2();
							returnStatus.enterBufQueue.add(didi);
							returnQueue.enterBufQueue.addAll(returnStatus.enterBufQueue);

							returnQueue.cacheQueue.addAll(returnStatus.cacheQueue);
							returnQueue.difPoint_dir_bufferMap.putAll(returnStatus.difPoint_dir_bufferMap);
							returnStatus.car_keepErrorPoint = 0;
							// 保留最后一个点的缓冲区
							returnStatus.difPoint_dir_bufferMap.clear();
							returnStatus.difPoint_dir_bufferMap.putAll(linkGeoList);
							// o.write("niuxinzan:保存这次最后一个点的分歧点id:" +
							// linkGeoList.keySet().toString());
							// 保留这次匹配的最后10个点
							updateCacheDiDi(returnStatus.enterBufQueue, returnStatus);
							// 清空enterbuffer点
							returnStatus.enterBufQueue.clear();
							// 添加缓冲区点到返回结果
							o.write("niuxinzan:得到匹配点");
							if (returnList.containsKey(carId)) {
								ArrayList<DidiQueue2> list = returnList.get(carId);
								list.add(returnQueue);
							} else {
								ArrayList<DidiQueue2> list = new ArrayList<DidiQueue2>();
								list.add(returnQueue);
								for (DiDiNewData1 ddd : returnQueue.enterBufQueue) {
									// System.out.println(ddd.timeStamp);
								}
								returnList.put(carId, list);
							}
						} else {
							returnStatus.enterBufQueue.add(didi);
							returnStatus.car_keepErrorPoint++;
							// return null;
						}
					}
					if (returnStatus.enterBufQueue.size() != 0 && !didi.difPointId.equals("")) {
						if (judgeBuffer(linkGeoList_bef, linkGeoList, didi)) {
							returnStatus.enterBufQueue.add(didi);
							returnStatus.difPoint_dir_bufferMap = linkGeoList_bef;
							returnStatus.car_keepErrorPoint = 0;
						} else {
							if (returnStatus.car_keepErrorPoint >= car_keepErrorPoint) {
								// 生成输出点序对象
								returnQueue = new DidiQueue2();
								returnStatus.enterBufQueue.add(didi);
								returnQueue.enterBufQueue.addAll(returnStatus.enterBufQueue);

								returnQueue.cacheQueue.addAll(returnStatus.cacheQueue);
								returnQueue.difPoint_dir_bufferMap.putAll(returnStatus.difPoint_dir_bufferMap);
								returnStatus.car_keepErrorPoint = 0;
								// 保留最后一个点的缓冲区
								returnStatus.difPoint_dir_bufferMap.clear();
								returnStatus.difPoint_dir_bufferMap.putAll(linkGeoList);

								// 保留这次匹配的最后10个点
								updateCacheDiDi(returnStatus.enterBufQueue, returnStatus);
								// 清空enterbuffer点
								returnStatus.enterBufQueue.clear();
								// 添加缓冲区点到返回结果
								o.write("niuxinzan:得到匹配点");
								if (returnList.containsKey(carId)) {
									ArrayList<DidiQueue2> list = returnList.get(carId);
									list.add(returnQueue);
								} else {
									ArrayList<DidiQueue2> list = new ArrayList<DidiQueue2>();
									list.add(returnQueue);
									returnList.put(carId, list);
								}
							} else {
								returnStatus.enterBufQueue.add(didi);
								returnStatus.car_keepErrorPoint++;
							}
						}
					}
				}
			}
		}
		return returnList;
	}

	private static boolean judgeBuffer(HashMap<String, DifPointTotalMapInfo> linkGeoList_bef, HashMap<String, DifPointTotalMapInfo> linkGeoList_now, DiDiNewData1 didi) throws IOException {
		// TODO Auto-generated method stub
		if (linkGeoList_bef == null || linkGeoList_bef.size() == 0) {
			o.write("这个地方不应该走！");
			return false;
		}

		ArrayList<String> difKeyList = new ArrayList<>();
		HashMap<String, DifPointTotalMapInfo> linkGeoMap = new HashMap<>();
		StringBuffer sb = new StringBuffer();
		for (Map.Entry<String, DifPointTotalMapInfo> entry : linkGeoList_bef.entrySet()) {
			String key = entry.getKey();
			// o.write("key1:" + key);
			if (linkGeoList_now.containsKey(key)) {
				linkGeoMap.put(key, entry.getValue());
				sb.append(key);
				sb.append("|");
			} else {
				difKeyList.add(key);
			}
		}
		if (linkGeoMap.size() != 0) {
			for (String key : difKeyList) {
				linkGeoList_bef.remove(key);
			}
			return true;

		}
		return false;
	}

	private static void updateCacheDiDi(LinkedList<DiDiNewData1> enterBufQueue, DidiQueueStatus2 returnStatus) {
		// TODO Auto-generated method stub
		int size = enterBufQueue.size();
		List<DiDiNewData1> list1 = enterBufQueue.subList((size - 10) > 0 ? (size - 10) : 0, size);
		returnStatus.cacheQueue.clear();
		for (DiDiNewData1 object : list1) {
			returnStatus.cacheQueue.add(object);
		}
	}

	private static void judgeIsInCacheBufferArea(DiDiNewData1 didi, DidiQueueStatus2 returnStatus) {
		// TODO Auto-generated method stub
		/**
		 * 如果cache缓存点最后一个点与didi的点属于同一个缓冲区则将cache数据加入到enterBufQueue，否则舍弃
		 */
		LinkedList<DiDiNewData1> cacheQueue = returnStatus.cacheQueue;
		int size = cacheQueue.size();
		String cacheDifPointId = cacheQueue.get(size - 1).difPointId;
		String didiDifPointId = didi.difPointId;
		if (!didiDifPointId.equals("") && !cacheDifPointId.equals("")) {
			String[] difIdArr = cacheDifPointId.split("\\|");
			for (String id : difIdArr) {
				didiDifPointId.contains(id);
				returnStatus.enterBufQueue.addAll(returnStatus.cacheQueue);
				break;
			}
		}
		returnStatus.cacheQueue.clear();
	}

	private static String getDifPointId(HashMap<String, DifPointTotalMapInfo> linkGeoList) {
		// TODO Auto-generated method stub
		if (linkGeoList.size() == 0) {
			return "";
		}
		StringBuffer sf = new StringBuffer();
		Set<String> difpointId_dir = linkGeoList.keySet();
		for (String difpoint : difpointId_dir) {
			sf.append(difpoint);
			sf.append("|");
		}
		String difPointId = sf.toString();
		if (difPointId.endsWith("|")) {
			difPointId = difPointId.substring(0, difPointId.length() - 1).toString();
		}
		return difPointId;
	}

	/**
	 * 20161121修改：对于平行的两个路，加入方位角判断
	 * 
	 * @param didi
	 * @param mapInfo
	 * @param beforeData
	 * @param i
	 * @return
	 */
	private static HashMap<String, DifPointTotalMapInfo> judgeIsInBufferArea(DiDiNewData1 didi, ArrayList<DifPointTotalMapInfo> mapInfo, DiDiNewData1 beforeData, int i) {
		// TODO Auto-generated method stub
		// double azimuth = didi.direction;
		Point point = MapUtil.getPoint(new Coordinate(didi.lon, didi.lat));
		double direction = MapUtil.azimuth(beforeData.lon, beforeData.lat, didi.lon, didi.lat);
		HashMap<String, DifPointTotalMapInfo> dataList = new HashMap<>();
		for (DifPointTotalMapInfo entry : mapInfo) {
			double enter = entry.enter_Azimuth;
			double outer = entry.out_Azimuth;
			String minMaxAngle11 = getminMaxAngle(enter);
			String minMaxAngle22 = getminMaxAngle(outer);
			Geometry geo = entry.roadGeo;
			// double nowAng1=azimuth+180;
			// double nowAng=nowAng1<=180?nowAng1:nowAng1-360;
			if (geo.contains(point)) {
//				System.out.println(didi.carID + "," + "direction:" + direction + "enter:" + enter + "outer:" + outer + ":" + beforeData.lon + ":" + beforeData.lat + ":" + didi.lon + ":" + didi.lat + ":" + didi.timeStamp);
				if (i == 0) {
					dataList.put(entry.dif_Point_Id + "_" + entry.flag, entry);
					System.out.println("第一个数据，并且在缓冲区里面，不考虑角度问题");
				} else {
					if (judgeAngle(minMaxAngle11, minMaxAngle22, direction)) {

						dataList.put(entry.dif_Point_Id + "_" + entry.flag, entry);
					} else {
						System.out.println("舍弃");
					}
				}

				// dataList.put(entry.dif_Point_Id + "_" + entry.flag, entry);
			}
		}

		return dataList;
	}

	private static boolean judgeAngle(String minMaxAngle1, String minMaxAngle2, double direction) {
		// TODO Auto-generated method stub
		String[] s1 = minMaxAngle1.split("\\:");
		String[] s2 = minMaxAngle2.split("\\:");
		for (String ss : s1) {
			String[] sss = ss.split("\\_");
			double minAngle = Double.parseDouble(sss[0]);
			double maxAngle = Double.parseDouble(sss[1]);
			if (direction >= minAngle && direction <= maxAngle) {
				return true;
			}
		}
		for (String ss : s2) {
			String[] sss = ss.split("\\_");
			double minAngle = Double.parseDouble(sss[0]);
			double maxAngle = Double.parseDouble(sss[1]);
			if (direction >= minAngle && direction <= maxAngle) {
				return true;
			}
		}
		return false;
	}

	private static String getminMaxAngle(double enter) {
		// TODO Auto-generated method stub
		// 角度在第一象限
		if (enter >= 0 && enter <= 90) {
			double s1 = enter - 90;
			double s2 = enter + 90;
			return s1 + "_" + s2;
		}

		// 第二象限
		if (enter > 90 && enter <= 180) {
			double s1 = enter - 270;
			double s2 = enter - 90;
			return "-180_" + s1 + ":" + s2 + "_" + 180;
		}
		// 第三象限
		if (enter >= -180 && enter < -90) {
			double s1 = enter + 90;
			double s2 = enter +270;
			return "-180_" + s1 + ":" + s2 + "_" + 180;
		}

		// 第四象限
		if (enter >= -90 && enter < 0) {
			double s1 = enter - 90;
			double s2 = enter + 90;
			return s1 + "_" + s2;
		}
		return null;

	}

	/**
	 * 读取地图数据
	 * 
	 * @param mapFilePath2
	 * @return
	 * @throws IOException
	 * @throws ParseException
	 */
	private static ArrayList<DifPointTotalMapInfo> readMapDataFile(String mapFilePath2) throws IOException, ParseException {
		// TODO Auto-generated method stub
		ArrayList<DifPointTotalMapInfo> mapData = new ArrayList<DifPointTotalMapInfo>();
		File file = new File(mapFilePath2);
		BufferedReader br = new BufferedReader(new FileReader(file));
		String line = "";
		while ((line = br.readLine()) != null) {
			mapData.add(DifPointTotalMapInfo.parseData1(line));
		}
		return mapData;
	}

	/**
	 * 
	 * @param didifilePath2
	 * @param meshSet2
	 * @return
	 * @throws IOException
	 */
	private static HashMap<String, TreeMap<Long, DiDiNewData1>> readDiDiDataFile(String didifilePath2, HashSet<Integer> meshSet2) throws IOException {
		// TODO Auto-generated method stub
		HashMap<String, TreeMap<Long, DiDiNewData1>> car_time_lineMap = new HashMap<String, TreeMap<Long, DiDiNewData1>>();
		String time = "";
		File[] files = new File(didifilePath2).listFiles();
		for (File file : files) {
			time = file.getName();
			System.out.println("----------------" + file.getName() + "-----------------");
			// if (!time.equals("830")) {
			// continue;
			// }
			BufferedReader br = new BufferedReader(new FileReader(file));
			String line = "";
			while ((line = br.readLine()) != null) {
				DiDiNewData1 didi = DiDiNewData1.parseData1(line);
				if (didi != null) {
					// if(didi.direction<-180||didi.direction>180)
					// continue;
					String carId = didi.carID;
					long timStamp = didi.timeStamp;
					int meshId = Integer.parseInt(MapUtil.findCell(didi.lon, didi.lat, 200).split("\\_")[0]);
					if (meshSet2.contains(meshId)) {
						if (car_time_lineMap.containsKey(carId)) {
							TreeMap<Long, DiDiNewData1> timeMap = car_time_lineMap.get(carId);
							timeMap.put(timStamp, didi);
						} else {
							TreeMap<Long, DiDiNewData1> timeMap = new TreeMap<Long, DiDiNewData1>();
							timeMap.put(timStamp, didi);
							car_time_lineMap.put(carId, timeMap);
						}
					}
				} else {
					// return null;
				}
			}
		}
		// o.write(car_time_lineMap.size());
		for (Map.Entry<String, TreeMap<Long, DiDiNewData1>> entry : car_time_lineMap.entrySet()) {
			String carId = entry.getKey();
			TreeMap<Long, DiDiNewData1> list = entry.getValue();
			for (Map.Entry<Long, DiDiNewData1> entry1 : list.entrySet()) {
				DiDiNewData1 didi = entry1.getValue();
				o.write(didi.lon + "," + didi.lat + "," + didi.timeStamp + "," + didi.carID + "," + "111");
				o.newLine();
				o.flush();
			}

		}
		return car_time_lineMap;
	}
}